home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / gfx / show / MerlinGfx.lha / MerlinFract.c < prev    next >
C/C++ Source or Header  |  1995-06-07  |  54KB  |  1,822 lines

  1.  
  2. /*    MerlinFract - produces Mandelbrot Sets with Merlin
  3.  
  4.         Rainer Trunz, January 1995
  5.  
  6.     This program calculates the so called "Mandelbrot Sets"
  7.     in a PIP-window on a Merlin graphic board
  8.  
  9.     History:
  10.     V1.1 21.01.1995  First version, already stable, 'Quick' and
  11.                      dirty hack, that is, it was meant as a 'simple'
  12.                      test for programming within a 2.6.1/2.3.3 - gcc
  13.                      baserel-environment (and the Merlin board, too).
  14.  
  15.     V1.2 26.01.1995  Second version, added doublclick-zoom
  16. */
  17.  
  18. #include "amiga.h"
  19.  
  20. #include <proto/icon.h>
  21.  
  22. #include <stdlib.h>
  23. #include <math.h>
  24.  
  25. #include <inline/strsup.h>
  26.  
  27. #include <sys/types.h>
  28. #include <sys/signal.h>
  29. #include <sys/time.h>
  30.  
  31. int __nocommandline=1; /* Disable commandline parsing  */
  32.  
  33. extern struct WBStartup *_WBenchMsg;
  34.  
  35. /* Define BOOLEAN, TRUE, and FALSE. */
  36.  
  37. #define BOOLEAN int
  38. #define TRUE      1
  39. #define FALSE     0
  40.  
  41. #define ENVNAME "MerlinFract.prefs"
  42. #define ENVSIZE 256
  43.  
  44. #define OUTPUT(s)      if (!quietFlag) FPrintf (stdout, s)
  45. #define OUTPUT1(s,a)   if (!quietFlag) FPrintf (stdout, s, a)
  46. #define OUTPUT2(s,a,b) if (!quietFlag) FPrintf (stdout, s, a, b)
  47.  
  48. #define SET_A_PEN(a)   OUTPUT1("\033[3%ldm", a)
  49.  
  50. #define BITS2SHIFT 27
  51.  
  52. /* something to use to track the time between messages
  53. ** to test for double-clicks.
  54. */
  55. typedef struct myTimeVal
  56. {
  57.     ULONG LeftSeconds;
  58.     ULONG LeftMicros;
  59.     ULONG RightSeconds;
  60.     ULONG RightMicros;
  61. } MYTIMEVAL;
  62.  
  63. /*============================================================================*
  64.  *  Oeffentliche Variablen / Strukturen.                                      *
  65.  *============================================================================*/
  66.  
  67. int quietFlag = FALSE;
  68. int verbose = FALSE;
  69.  
  70. int ZoomNr = 0;
  71. int ZoomBox = 8;        /* 1/xth of InnerWidth/Height */
  72. int ZoomFlag = FALSE;
  73.  
  74. BOOL IEEEflag = FALSE;
  75.  
  76. struct Device        *TimerBase    = NULL;
  77. struct timerequest    *TimerIO    = NULL;
  78. struct MsgPort        *TimerPort    = NULL;
  79. struct EClockVal    time0        = {NULL};
  80. struct EClockVal    time1        = {NULL};
  81.  
  82. ULONG timerclosed = TRUE;
  83. double micros_per_eclock;    /* Length of EClock tick in microseconds */
  84.  
  85. char fileName[256];
  86.  
  87. struct ExecBase         *SysBase = NULL;
  88. struct IntuitionBase *IntuitionBase = NULL;
  89. struct GfxBase       *GfxBase       = NULL;
  90. struct Library       *GadToolsBase  = NULL;
  91. struct Library       *AslBase       = NULL;
  92. struct Library       *HRGSystemBase = NULL,
  93.                      *HRGRenderBase = NULL;
  94. struct HRHandle      *hrh = NULL;
  95.  
  96. BPTR fd = NULL;                /* The main file descriptor */
  97. BPTR stdout = NULL;            /* Standard Output  */
  98.  
  99. ULONG FrameSize = NULL;
  100.  
  101. int offx = 0, offy = 0,
  102.     offl = 0, offt = 0;
  103.  
  104. struct IntPotParms {
  105.  int C_Real;
  106.  int C_Imag;
  107.  int ScreenReal;
  108.  int ScreenImag;
  109.  int MaxIter;
  110. };
  111.  
  112. double RealLow, ImagLow;
  113. double RealHigh, ImagHigh;
  114.  
  115. double RealGap, ImagGap;
  116.  
  117. int MaxIteration = 32;
  118.  
  119. /*============================================================================*
  120.  *  Lokale Variablen / Strukturen.                                            *
  121.  *============================================================================*/
  122.  
  123. static struct Window        *FRA_win = NULL;
  124. static struct RastPort      *rp      = NULL;
  125. static struct IntuiMessage  *imsg    = NULL;
  126. static struct Screen        *Screen  = NULL;
  127. static struct Menu          *Menus   = NULL;
  128. static struct IntuiMessage  msg;
  129.  
  130. static struct HRBitMap      *hrbm    = NULL;
  131. static struct HRModePrefDat MyPrefs;
  132.  
  133. static APTR VisualInfo = NULL;
  134.  
  135. static UWORD CurrentGadget = NO_GADGET;
  136. static ULONG soerror = 0;
  137.  
  138. ULONG *coltab = NULL, *curctab = NULL;
  139.  
  140. static int InnerWidth = 0, InnerHeight = 0,
  141.            ScrollX = 0, ScrollY = 0,
  142.            Width = 0, Height = 0,
  143.            left = 0, top = 0;
  144.  
  145. static struct Gadget *LeftGadget  = NULL,
  146.                      *RightGadget = NULL,
  147.                      *UpGadget    = NULL,
  148.                      *DownGadget  = NULL,
  149.                      *HorizGadget = NULL,
  150.                      *VertGadget  = NULL;
  151.  
  152. static struct Image  *UpImage     = NULL,
  153.                      *DownImage   = NULL,
  154.                      *LeftImage   = NULL,
  155.                      *RightImage  = NULL;
  156.  
  157. static struct NewMenu NewMenu[] = {
  158.     NM_TITLE, (STRPTR)"Project",            NULL,       0, 0L, NULL,
  159.     NM_ITEM,  (STRPTR)"About...",          (STRPTR)"?", 0, 0L, NULL,
  160.     NM_ITEM,  (STRPTR)NM_BARLABEL,          NULL,       0, 0L, NULL,
  161.     NM_ITEM,  (STRPTR)"Use Int  (32 Bit)",  NULL, CHECKIT|CHECKED, 8L, NULL,
  162.     NM_ITEM,  (STRPTR)"Use IEEE (64 Bit)",  NULL, CHECKIT, 4L, NULL,
  163.     NM_ITEM,  (STRPTR)"Reset Mand",        (STRPTR)"M", 0, 0L, NULL,
  164.     NM_ITEM,  (STRPTR)NM_BARLABEL,          NULL,       0, 0L, NULL,
  165.     NM_ITEM,  (STRPTR)"Quit",              (STRPTR)"Q", 0, 0L, NULL,
  166.     NM_TITLE, (STRPTR)"Window",             NULL      , 0, 0L, NULL,
  167.     NM_ITEM,  (STRPTR)"Reset To Defaults", (STRPTR)"R", 0, 0L, NULL,
  168.     NM_ITEM,  (STRPTR)"Save As Defaults",  (STRPTR)"S", 0, 0L, NULL,
  169.     NM_ITEM,  (STRPTR)"Last Saved",        (STRPTR)"L", 0, 0L, NULL,
  170.     NM_ITEM,  (STRPTR)NM_BARLABEL,          NULL,       0, 0L, NULL,
  171.     NM_ITEM,  (STRPTR)"Minimize",          (STRPTR)"-", 0, 0L, NULL,
  172.     NM_ITEM,  (STRPTR)"Maximize",          (STRPTR)"+", 0, 0L, NULL,
  173.     NM_END,   NULL, NULL, 0, 0L,   NULL };
  174.  
  175. static struct EasyStruct AboutRequest = {
  176.     sizeof(struct EasyStruct),
  177.     0,
  178.     "MerlinFract/C",
  179.     "Mandelbrot Displayer\n"
  180.     "for the Merlin Graphics Accelerator\n\n"
  181.     "Version 1.2 ("__DATE__")\n\n"
  182.     "Copyright © 1995 Rainer Trunz",
  183.     "Continue"
  184. };
  185.  
  186. static char *version = "$VER: MerlinFract 1.2 ("__DATE__")";
  187.  
  188. static int wwidth, wheight;    /* Width and height of the window */
  189.  
  190. /* prototypes */
  191.  
  192. #ifndef LARGE
  193.  
  194. /*****************************************************************************
  195.  *
  196.  *  EasyReqArgs.asm    - EasyRequestArgs() für baserel Gnu-C ;-(((
  197.  *
  198.  *  ©`94 Rainer F. Trunz. Geschrieben für Gnu-C 2.3.3 !
  199.  *
  200.  *****************************************************************************/
  201.  
  202. ULONG EasyReqArgs (struct Window *window, struct EasyStruct *easyStruct,
  203.                          ULONG *idcmpPtr, ULONG args,...)
  204. {
  205.   __asm __volatile ("            | (ostring, format, {values})
  206.  
  207.     moveml    a2/a3/a6,sp@-
  208.  
  209.     lea        sp@(4*4),a3
  210.     moveml    a3@+,a0/a1/a2        | a3 is now ptr to tag-field
  211.     movel    a4@(_IntuitionBase:W),a6
  212.     jsr        a6@(-588)            | _LVOEasyRequestArgs
  213.  
  214.     moveml    sp@+,a2/a3/a6"
  215.  
  216.     : /* No Output */
  217.     : /* No Input */
  218.     : "d0","d1","a0","a1");
  219. }
  220.  
  221. /*****************************************************************************
  222.  *
  223.  *  SetGadAttrs.asm - SetGadgetAttrsA() für baserel Gnu-C ;-(((
  224.  *
  225.  *  ©`94 Rainer F. Trunz. Geschrieben für Gnu-C 2.3.3 !
  226.  *
  227.  *****************************************************************************/
  228.  
  229. ULONG SetGadAttrs (struct Gadget *gad, struct Window *win,
  230.                         struct Requester *req, ULONG args,...)
  231. {
  232.   __asm __volatile ("
  233.  
  234.     moveml    a2/a3/a6,sp@-
  235.  
  236.     lea        sp@(4*4),a3
  237.     moveml    a3@+,a0/a1/a2        | a3 is now ptr to tag-field
  238.     movel    a4@(_IntuitionBase:W),a6
  239.     jsr        a6@(-660)            | _LVOSetGadgetAttrsA
  240.  
  241.     moveml    sp@+,a2/a3/a6"
  242.  
  243.     : /* No Output */
  244.     : /* No Input */
  245.     : "d0","d1","a0","a1");
  246. }
  247.  
  248. #endif
  249.  
  250. /*****************************************************************************
  251.  * 32 bit fixed point generator
  252.  */
  253.  
  254. static inline int Int32_Height_Fast (struct IntPotParms *Parms)
  255. {
  256.   register int _res __asm("d0");
  257.   register struct IntPotParms * a2 __asm("a2") = Parms;
  258.  
  259.   __asm __volatile ("
  260.  
  261. fscreeni    =    4            | fscreenr    = 0
  262. fcurx        =    8
  263. fcury        =    12
  264. maxi        =    16
  265.  
  266. Zcurx        =    8
  267. Zcury        =    12
  268.  
  269.     | d1 - BITS2SHIFT
  270.     | d2 - k
  271.     | d4 - a
  272.     | d5 - b
  273.     | d6 - a2
  274.     | d7 - b2
  275.  
  276.     | cura = curb = curc = curd = 0;
  277.  
  278.    movel   a2@(maxi),d1
  279.    moveq   #27,d2
  280.    movel   a2@,d4
  281.    movel   a2@(fscreeni),d5
  282.    movel   d4,a0            | a2@(fcurx),a0
  283.    movel   d5,a1            | a2@(fcury),a1
  284.    jra     Zpos2
  285.  
  286. ZLoop:    | cura = cura2 - curb2 + curx;
  287.  
  288.    exg     d6,d4
  289.    subl    d7,d4            |  movel   a0,d0
  290.    addl    a0,d4
  291.    mulsl   d6,d0:d5            | curb = cura * curb
  292.    asll    #5,d0
  293.    lsrl    d2,d5
  294.    orl     d0,d5            | curb += curb + cury;
  295.    addl    d5,d5            |  movel   a1,d0
  296.    addl    a1,d5
  297.  
  298. Zpos2:    | cura2 = cura * cura;
  299.  
  300.    movel   d4,d6
  301.    mulsl   d6,d0:d6
  302.    asll    #5,d0
  303.    jvs     Zbailout
  304.  
  305.    lsrl    d2,d6
  306.    orl     d0,d6
  307.    movel   d5,d7            | curb2 = curb * curb;
  308.    mulsl   d7,d0:d7
  309.    asll    #5,d0
  310.    jvs     Zbailout
  311.  
  312.    lsrl    d2,d7
  313.    orl     d0,d7
  314.  
  315.    movel   d6,d0
  316.    addl    d7,d0            | cmpl    #536870912,d0
  317.    jvs     Zbailout            | bge      Zbailout
  318.  
  319.    dbra    d1,ZLoop            | addq     #1,d1
  320.    moveq   #1,d0            | black
  321.    jra       setBl
  322.  
  323. Zbailout:
  324.    movel   a2@(maxi),d0
  325.    subw    d1,d0            | subqw   #1,d0
  326.    extl    d0
  327. setBl:"
  328.     : "=r" (_res)
  329.     : "r" (a2)
  330.     : "d0","d1","d2","d4","d5","d6","d7","a0","a1");
  331.  
  332.     return _res;
  333. }
  334.  
  335. /* void SyncWait(secs, microsecs);
  336.    wait for specified amount of time and then return */
  337.  
  338. static inline void
  339. SyncWait (unsigned long secs, unsigned long microsecs)
  340. {
  341.   struct timeval tv_temp;
  342.  
  343.   tv_temp.tv_secs = secs;
  344.   tv_temp.tv_micro = microsecs;
  345.  
  346.   TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  347.   TimerIO->tr_time = tv_temp;
  348.  
  349.   DoIO ((struct IORequest *) TimerIO);
  350. }
  351.  
  352. /*============================================================================*/
  353.  
  354. #ifdef HACK
  355.  
  356. static inline void
  357. hrWriteRect (struct HRBitMap *hrbm, UBYTE *buf,
  358.              int srcx,  int srcy,
  359.              int width, int height)
  360. {
  361.     UBYTE *src, *dest;
  362.     int anz, i, mod;
  363.  
  364. /*    UWORD BytesPerRow;
  365.     UWORD Rows;
  366.     UBYTE PixelModulo;
  367.     ULONG ByteSize;
  368.  
  369.     PixelModulo = (hrbm)->PixelModulo;
  370.     Rows = (hrbm)->Rows;
  371.     BytesPerRow = (hrbm)->BytesPerRow;
  372.     ByteSize = (hrbm)->ByteSize;
  373. */
  374.     hrSLockBitMap (hrbm);
  375.  
  376.     if (!srcx && !srcy && (width == InnerWidth) && (height == InnerHeight))
  377.       CopyMemQuick (buf, (hrbm)->MemPtr[0], FrameSize);
  378.     else {
  379.       mod  = srcy*InnerWidth;
  380.       dest = (hrbm)->MemPtr[0] + mod;
  381.       src  = buf + mod;
  382.       i    = width;
  383.  
  384.       /* printf ("srcx: %ld, srcy: %ld, W: %ld, H: %ld, mod: %ld\n",
  385.         srcx, srcy, width, height, mod); */
  386.  
  387.       for (anz = 0; anz < height; anz++,
  388.                                   mod += InnerWidth,
  389.                                   dest = (hrbm)->MemPtr[0] + mod + srcx,
  390.                                   src = buf + mod + srcx,
  391.                                   i = width)
  392.         while (i)
  393.           {*(dest++) = *(src++); i--;}
  394.     }
  395.     hrUnlockBitMap (hrbm);
  396. }
  397.  
  398. #endif
  399.  
  400. /*============================================================================
  401.  *
  402.  * contents: this file contains the functions to calculate Mandelbrot and
  403.  * Julia pictures using a special and fast fixed point (scaled ints) format.
  404.  * It has generators for 68000 and 68020 in assembly.
  405.  */
  406.  
  407. /* 32 bit fixed point generator */
  408.  
  409. void MandelbrotInt32II()
  410. {
  411.   int i, j;        /* struct RastPort *Rp; */
  412.  
  413.   UBYTE *CountPtr;
  414.   int gapx, gapy, startx;
  415.  
  416.   struct IntPotParms Parms;
  417.   double time;
  418.  
  419.   RealGap = (RealHigh - RealLow) / (double)InnerWidth;
  420.   ImagGap = (ImagHigh - ImagLow) / (double)InnerHeight;
  421.  
  422.   /* Figure out horizontal and verticle distances between points in plane.
  423.    * Convert them to fixed point format */
  424.  
  425.   gapy     = (int) (ImagGap*((double)(1<<BITS2SHIFT)));
  426.   gapx     = (int) (RealGap*((double)(1<<BITS2SHIFT)));
  427.  
  428.   startx = (int) (RealLow*((double)(1<<BITS2SHIFT)));
  429.  
  430.   /* for each point in the image, calculate Mandelbrot */
  431.  
  432.   Parms.C_Imag = (int)(ImagLow*((double)(1<<BITS2SHIFT)));
  433.  
  434.   Parms.ScreenReal = 0;
  435.   Parms.ScreenImag = 0;
  436.  
  437.   Parms.MaxIter = MaxIteration;
  438.  
  439.   if (TimerBase)
  440.     ReadEClock (&time0);    /* start time */
  441.  
  442.   hrSLockBitMap (hrbm);
  443.   CountPtr = (hrbm)->MemPtr[0];
  444.  
  445.   for (i = 0; i < InnerHeight; i++) {
  446.      Parms.C_Real = startx;
  447.  
  448.      for (j = 0; j < InnerWidth; j++) {
  449.         *CountPtr++ = Int32_Height_Fast (&Parms);
  450.         Parms.C_Real += gapx;
  451.      }
  452.      Parms.C_Imag += gapy;
  453.   }
  454.   hrUnlockBitMap (hrbm);
  455.  
  456.   if (TimerBase) {
  457.     ReadEClock (&time1);    /* find out and display how long it took */
  458.  
  459.     time = ((time1.ev_hi - time0.ev_hi) * 4294967296.0 +
  460.             (time1.ev_lo - time0.ev_lo)) * micros_per_eclock;
  461.  
  462.     Printf ("\nTime = %02ld:%02ld.%ld [m:s.µ]\n",
  463.             (int) ((time / 1000000.0) / 60.0),
  464.             (int) ((time / 1000000.0) - ((int)((int)(time / 1000000.0) / 60.0) * 60)),
  465.             (int) fmod (time, 1000000.0) / 10000);
  466.   }
  467. } /* MandelbrotInt32II */
  468.  
  469. /*============================================================================*
  470.  * FPU Mandelbrot Set
  471.  *============================================================================*/
  472.  
  473. /* This function calculates the 'potential' of a given location
  474.  * in the complex plane. */
  475.  
  476. static __inline int DBL_Height (double posx, double posy, double juliax, double juliay)
  477.  
  478.     /* posx;        Location in screen coordinate space         */
  479.     /* posy;        Location in screen coordinate space         */
  480.     /* juliax:    Real part of location on complex plane      */
  481.     /* juliay;    Imaginary part of location on complex plane */
  482. {
  483.   double cura, curb;
  484.   double cura2, curb2;
  485.  
  486.   double DBL16 = 16.0;
  487.  
  488.   LONG k;
  489.  
  490.   cura = cura2 = posx;
  491.   curb = curb2 = posy;
  492.  
  493.   cura2 = cura2*cura2;
  494.   curb2 = curb2*curb2;
  495.  
  496.   for (k = 0; k < MaxIteration; k ++ ) {
  497.  
  498.     curb = curb*cura;                /* b = 2 * a * b  + juliay */
  499.     curb = curb+curb+juliay;
  500.  
  501.     cura = cura2-curb2+juliax;        /* a = a2 - b2 + juliax */
  502.  
  503.     cura2 = cura*cura;                /* a2 = a * a */
  504.     curb2 = curb*curb;                /* b2 = b * b */
  505.  
  506.     if (cura2+curb2 >= DBL16)        /* quit if a2+b2 is too big */
  507.       return (k==1 ? k+3:k);
  508.   }
  509.   return 1L;                        /* Black for set ! */
  510. }
  511.  
  512. /* This is also a Mandelbrot potential calculator, that is tailored to
  513.  * identify points that are 'in' the Mandelbrot set. Points outside the
  514.  * Mandelbrot set diverge.  Points inside converge.
  515.  * This code uses a trace table mechanism to detect convergence.
  516.  */
  517.  
  518. static __inline int DBL_Trace_Height (double posx, double posy, double curx, double cury)
  519.  
  520.    /* posx; Real part of location on complex plane      */
  521.    /* posy; Imaginary part of location on complex plane */
  522.  
  523.    /* curx; Real part of location on complex plane      */
  524.    /* cury; Imaginary part of location on complex plane */
  525. {
  526.   LONG  k, l;
  527.  
  528.   LONG TraceSize = 32;
  529.  
  530.   double olda[32], oldb[32]; /* Convergence trace table */
  531.  
  532.   double cura, curb, cura2, curb2;
  533.   double *RealTrace, *ImagTrace;
  534.  
  535.   double DBL16 = 16.0;
  536.  
  537.   cura = cura2 = posx;
  538.   curb = curb2 = posy;
  539.  
  540.   cura2 = cura2*cura2;
  541.   curb2 = curb2*curb2;
  542.  
  543.   for (k = 0; k < MaxIteration; k += TraceSize) {
  544.     RealTrace = olda;
  545.     ImagTrace = oldb;
  546.  
  547.     for (l = 0; l < TraceSize; l++) {
  548.      *(RealTrace++) = cura;
  549.      *(ImagTrace++) = curb;
  550.  
  551.      curb = curb*cura;                /* b = 2 * a * b  + juliay */
  552.      curb = curb+curb+cury;
  553.  
  554.      cura = cura2-curb2+curx;        /* a = a2 - b2 + juliax */
  555.  
  556.      cura2 = cura*cura;                /* a2 = a * a */
  557.      curb2 = curb*curb;                /* b2 = b * b */
  558.  
  559.       if (cura2+curb2 >= DBL16)        /* quit if a2+b2 is too big */
  560.         return ((k+l)==1 ? k+l+3:k+l);
  561.     }
  562.  
  563.     /* Scope out trace table for convergence */
  564.  
  565.     RealTrace = olda;
  566.     ImagTrace = oldb;
  567.  
  568.     for (l = 0; l < TraceSize; l++)
  569.       if ((cura == *(RealTrace++)) && (curb == *(ImagTrace++))) {
  570.         /* k += MaxIter; */
  571.         return (MaxIteration);
  572.       }
  573.   }
  574.   return 1L;                        /* Black for set ! */
  575. }
  576.  
  577. /*** IEEE double-floating Point Mandelbrot Generator ***/
  578.  
  579. void Mandelbrot881()
  580. {
  581.   int i, j, k;
  582.   UBYTE *CountPtr;
  583.  
  584.   double time;
  585.   double curx, cury;
  586.   double startx, starty;    /* gapx, gapy; */
  587.  
  588.   BOOL MandFlag;
  589.  
  590.   RealGap = (RealHigh - RealLow) / (double)InnerWidth;
  591.   ImagGap = (ImagHigh - ImagLow) / (double)InnerHeight;
  592.  
  593.   startx = RealLow;
  594.   starty = ImagLow;
  595.  
  596.   /* start in the upper left hand corner */
  597.  
  598.   cury = starty;
  599.  
  600.   if (TimerBase)
  601.     ReadEClock (&time0);    /* start time */
  602.  
  603.   hrSLockBitMap (hrbm);
  604.   CountPtr = (hrbm)->MemPtr[0];
  605.  
  606.   for (i = 0; i < InnerHeight; i++) {        /* for each row */
  607.     curx = startx;
  608.     MandFlag = 0;
  609.     for (j = 0; j < InnerWidth; j++) {        /* for each column */
  610.  
  611.     /* if we've hit a Mandelbrot point,
  612.        then use the convergence detector
  613.        to reduce compute time */
  614.  
  615.       if (MandFlag)
  616.         k = DBL_Trace_Height (0.0, 0.0, curx, cury);
  617.       else
  618.         k = DBL_Height (0.0, 0.0, curx, cury);    /* Normal calculator */
  619.  
  620.       MandFlag = (k == MaxIteration);
  621.       *CountPtr = k;                        /* save it in ram */
  622.       CountPtr++;
  623.       curx = curx + RealGap;
  624.     }
  625.     cury = cury + ImagGap;
  626.   }
  627.   hrUnlockBitMap (hrbm);
  628.  
  629.   if (TimerBase) {
  630.     ReadEClock (&time1);    /* find out and display how long it took */
  631.  
  632.     time = ((time1.ev_hi - time0.ev_hi) * 4294967296.0 +
  633.             (time1.ev_lo - time0.ev_lo)) * micros_per_eclock;
  634.  
  635.     Printf ("\nTime = %02ld:%02ld.%ld [m:s.µ]\n",
  636.             (int) ((time / 1000000.0) / 60.0),
  637.             (int) ((time / 1000000.0) - ((int)((int)(time / 1000000.0) / 60.0) * 60)),
  638.             (int) fmod (time, 1000000.0) / 10000);
  639.   }
  640. } /* Mandelbrot881 */
  641.  
  642. /*============================================================================*
  643.  * Reset Mandelbrot Set
  644.  *============================================================================*/
  645.  
  646. static void
  647. ResetMand()
  648. {
  649.     ZoomNr = 0;
  650.     ZoomFlag = TRUE;
  651.     MaxIteration = 32;
  652.  
  653.     RealLow = -2.1;
  654.     ImagLow = -1.125;
  655.     RealHigh = 0.5;
  656.     ImagHigh = 1.125;
  657. }
  658.  
  659. /*============================================================================*
  660.  * Calculate Zoom-Area
  661.  *============================================================================*/
  662.  
  663. static void
  664. DoZoom (struct IntuiMessage *msg)
  665. {
  666.     int Breite, Hoehe;
  667.     double tmp;
  668.  
  669.     ZoomNr++;
  670.     ZoomFlag = TRUE;
  671.     MaxIteration += MaxIteration/2;
  672.  
  673.     Breite = InnerWidth  / ZoomBox;
  674.     Hoehe  = InnerHeight / ZoomBox;
  675.  
  676.     tmp = RealLow;
  677.     RealLow  = tmp + RealGap * ((msg->MouseX - left) - Breite/2);
  678.     RealHigh = tmp + RealGap * ((msg->MouseX - left) + Breite/2);
  679.     tmp = ImagLow;
  680.     ImagLow  = tmp + ImagGap * ((msg->MouseY - top) - Hoehe/2);
  681.     ImagHigh = tmp + ImagGap * ((msg->MouseY - top) + Hoehe/2);
  682.  
  683.     SetWindowTitles (FRA_win, -1L, GetTitle (fileName));
  684. }
  685.  
  686. /*============================================================================*/
  687.  
  688. int
  689. ASLRequestFile (char *Dir)
  690. {
  691.     struct FileRequester *FileRequester;
  692.     char buffer[256];
  693.     BOOL Result = FALSE;
  694.     struct TagItem tags[6];
  695.     LONG cnt = 0;
  696.  
  697.     SETTAG (ASL_Hail,       "Select Fractal file...");
  698.     SETTAG (ASL_OKText,     "Load");
  699.     SETTAG (ASL_CancelText, "Cancel");
  700.  
  701.     if (Dir && strlen(Dir)) {
  702.         SETTAG (ASL_Dir, Dir);
  703.     }
  704.  
  705.     SETTAG (TAG_END, 0);
  706.  
  707.     if (AslBase = OpenLibrary ("asl.library", 37)) {
  708.         if (FileRequester = (struct FileRequester *) AllocAslRequest (ASL_FileRequest, tags)) {
  709.             if (AslRequest (FileRequester, NULL)) {
  710.                 strcpy (buffer, FileRequester->rf_Dir);
  711.                 AddPart (buffer, FileRequester->rf_File, 255);
  712.                 strcpy (fileName, buffer);
  713.                 Result = TRUE;
  714.             }
  715.             FreeAslRequest (FileRequester);
  716.         }
  717.         CloseLibrary (AslBase);
  718.     }
  719.     return Result;
  720. }
  721.  
  722. /*============================================================================*
  723.  *  Alles ausser den Libraries schliessen und den Speicher wieder freigeben.  *
  724.  *============================================================================*/
  725.  
  726. void
  727. CloseDown (void)
  728. {
  729.     if (!timerclosed) {
  730.       CloseDevice ((struct IORequest *) TimerIO);
  731.       if (TimerPort) {
  732.         DeleteMsgPort (TimerPort);
  733.         TimerPort = NULL;
  734.       }    
  735.       if (TimerIO) {
  736.         DeleteIORequest ((struct IORequest *) TimerIO);
  737.         TimerIO = NULL;
  738.       }    
  739.       timerclosed = TRUE;
  740.       TimerBase = NULL;
  741.     }
  742.     if (FRA_win) {
  743.       if (Menus) {
  744.           ClearMenuStrip (FRA_win);
  745.           FreeMenus (Menus);
  746.           Menus = NULL;
  747.       }
  748.       if (VisualInfo) {
  749.           FreeVisualInfo (VisualInfo);
  750.           VisualInfo = NULL;
  751.       }
  752.       CloseWindow (FRA_win);
  753.       FRA_win = NULL;
  754.     }
  755.  
  756.     if (hrh) {
  757.  
  758.       hrSwitchSecondView (hrh, FALSE);
  759.  
  760.       if (coltab) {
  761.         hrSetPaletteRGBA (hrh, coltab, 0, 255);
  762.         free (coltab);
  763.         coltab = NULL;
  764.       }
  765.  
  766.       if (curctab) {
  767.         free (curctab);
  768.         curctab = NULL;
  769.       }
  770.  
  771.       hrFreeSecondView(hrh);
  772.       hrh = NULL;
  773.     }
  774.  
  775.     if (UpImage)     DisposeObject (UpImage);
  776.     if (DownImage)   DisposeObject (DownImage);
  777.     if (LeftImage)   DisposeObject (LeftImage);
  778.     if (RightImage)  DisposeObject (RightImage);
  779.     if (LeftGadget)  DisposeObject (LeftGadget);
  780.     if (RightGadget) DisposeObject (RightGadget);
  781.     if (UpGadget)    DisposeObject (UpGadget);
  782.     if (DownGadget)  DisposeObject (DownGadget);
  783.     if (VertGadget)  DisposeObject (VertGadget);
  784.     if (HorizGadget) DisposeObject (HorizGadget);
  785.  
  786.     UpImage = DownImage = LeftImage = RightImage = NULL;
  787.     LeftGadget = RightGadget = HorizGadget = NULL;
  788.     UpGadget   = DownGadget  = VertGadget  = NULL;
  789.  
  790.     if (HRGSystemBase) CloseLibrary(HRGSystemBase);
  791.                        HRGSystemBase = NULL;
  792.     if (HRGRenderBase) CloseLibrary(HRGRenderBase);
  793.                        HRGRenderBase = NULL;
  794.     if (GadToolsBase)  CloseLibrary(GadToolsBase);
  795.                        GadToolsBase = NULL;
  796.     if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  797.                        IntuitionBase = NULL;
  798.     if (GfxBase)       CloseLibrary((struct Library *) GfxBase);
  799.                        GfxBase = NULL;
  800. }
  801.  
  802. /*============================================================================*
  803.  *  Programm mit einer Fehlermeldung beenden                                  *
  804.  *============================================================================*/
  805.  
  806. void
  807. Quit (int failcode)
  808. {
  809.     char *ErrMsg = "";
  810.  
  811.     if (!quietFlag) {
  812.         switch (failcode) {
  813.             case NO_ERR  : break;
  814.             case REQ_ERR : break;
  815.             case PAR_ERR : break;
  816.             case MEM_ERR : ErrMsg = "Out of memory"; break;
  817.             case GFX_ERR : ErrMsg = "Need graphics.library V37"; break;
  818.             case INT_ERR : ErrMsg = "Need intuition.library V37"; break;
  819.             case SYS_ERR : ErrMsg = "Need hrgsystem.library V38"; break;
  820.             case REN_ERR : ErrMsg = "Need hrgrender.library V38"; break;
  821.             case DBL_ERR : ErrMsg = "Can't open two PIP Windows"; break;
  822.             case SCR_ERR : ErrMsg = "Can't open Merlin-Screen"; break;
  823.             case WIN_ERR : ErrMsg = "Can't open Window"; break;
  824.             case FND_ERR : ErrMsg = "Can't find Merlin-Screen"; break;
  825.             case PIP_ERR : ErrMsg = "Screen for PIP to small (640x400)"; break;
  826.             case DRI_ERR : ErrMsg = "Can't get ScreenDrawInfo"; break;
  827.             case MPG_ERR : ErrMsg = "This is no Fractal File"; break;
  828.             case RNG_ERR : ErrMsg = "Fatal error. Ring buffer full."; break;
  829.             case GET_ERR : ErrMsg = "Unexpected read error."; break;
  830.             case BRK_ERR : ErrMsg = "Interrupted!"; break;
  831.             case GAD_ERR : ErrMsg = "Need gadtools.library V37"; break;
  832.             case VIS_ERR : ErrMsg = "Can't get VisualInfo"; break;
  833.             case MEN_ERR : ErrMsg = "Can't create Menu"; break;
  834.             case TIM_ERR : ErrMsg = "Can't open timer.device"; break;
  835.             default:       ErrMsg = "Unknown error";
  836.         }
  837.         OUTPUT1 ("\n%s\n", ErrMsg);
  838.     }
  839.     CloseDown ();
  840.     exit (failcode);
  841. }
  842.  
  843. /*============================================================================*
  844.  *  Display allgemein initialisieren durch Oeffnen der Libraries.             *
  845.  *============================================================================*/
  846.  
  847. void
  848. InitLibraries (void)
  849. {
  850.     SysBase = (struct ExecBase *)(*(void **)4);
  851.  
  852.     if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 37))) {
  853.         Quit (GFX_ERR);
  854.     }
  855.     if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37))) {
  856.         Quit (INT_ERR);
  857.     }
  858.     if (!(GadToolsBase = (struct Library *) OpenLibrary ("gadtools.library", 37))) {
  859.         Quit (GAD_ERR);
  860.     }
  861.     if (!(HRGSystemBase = (struct Library *) OpenLibrary ("hrgsystem.library", 38))) {
  862.         Quit (SYS_ERR);
  863.     }
  864.     if (!(HRGRenderBase = (struct Library *) OpenLibrary ("hrgrender.library", 38))) {
  865.         Quit (REN_ERR);
  866.     }
  867.  
  868. /*============================================================================*
  869.  * timer stuff
  870.  *============================================================================*/
  871.  
  872.     /* message port for communicating with timer device */
  873.  
  874.     if (!(TimerPort = CreateMsgPort()))
  875.         Quit (TIM_ERR);
  876.  
  877.     /* our primary IO structure */
  878.  
  879.     if (!(TimerIO = (struct timerequest *)
  880.       CreateIORequest (TimerPort, sizeof(struct timerequest))))
  881.         Quit (TIM_ERR);
  882.  
  883.     if (timerclosed = OpenDevice (TIMERNAME, UNIT_VBLANK,
  884.                         (struct IORequest *) TimerIO, 0))
  885.         Quit (TIM_ERR);
  886.  
  887.     TimerBase = (struct Library *) TimerIO->tr_node.io_Device;
  888.  
  889.     micros_per_eclock = 1000000.0 / (double)ReadEClock (&time0);
  890. }
  891.  
  892. /*============================================================================*
  893.  *  Window und SecondView PIP vergoessern/verkleinern.                        *
  894.  *============================================================================*/
  895.  
  896. static void
  897. Resize (void)
  898. {
  899.     ULONG HorizPot, VertPot, dX, dY;
  900.  
  901.     GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
  902.     GetAttr (PGA_Top, VertGadget,  (ULONG *)&VertPot);
  903.  
  904.     hrResizeSecondView (hrh, FRA_win->Width - Screen->WBorLeft - DownImage->Width,
  905.                              FRA_win->Height - (Screen->Font->ta_YSize + Screen->WBorTop + 1) - RightImage->Height);
  906. #ifndef LARGE
  907.     SetGadAttrs (HorizGadget, FRA_win, NULL,
  908.         PGA_Top,      HorizPot,
  909.         PGA_Visible,  FRA_win->Width,
  910.         PGA_Total,    Width,
  911.         TAG_DONE);
  912. #else
  913.     SetGadgetAttrs (HorizGadget, FRA_win, NULL,
  914.         PGA_Top,      HorizPot,
  915.         PGA_Visible,  FRA_win->Width,
  916.         PGA_Total,    Width,
  917.         TAG_DONE);
  918. #endif
  919.  
  920.     GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
  921.  
  922. #ifndef LARGE
  923.     SetGadAttrs (VertGadget, FRA_win, NULL,
  924.         PGA_Top,      VertPot,
  925.         PGA_Visible,  FRA_win->Height,
  926.         PGA_Total,    Height,
  927.         TAG_DONE);
  928. #else
  929.     SetGadgetAttrs (VertGadget, FRA_win, NULL,
  930.         PGA_Top,      VertPot,
  931.         PGA_Visible,  FRA_win->Height,
  932.         PGA_Total,    Height,
  933.         TAG_DONE);
  934. #endif
  935.  
  936.     GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
  937.  
  938.     hrScrollSecondView (hrh, dX, dY);
  939.     ScrollX = dX; ScrollY = dY;
  940. }
  941.  
  942. /*============================================================================*
  943.  *  Auf Knopfdruck und Verschieben der Rollbalken reagieren.                  *
  944.  *============================================================================*/
  945.  
  946. static void
  947. CheckGadget (UWORD GadgetID)
  948. {
  949.     int step, HorizPot, VertPot;
  950.     ULONG dX = ScrollX, dY = ScrollY;
  951.  
  952.     switch (GadgetID) {
  953.         case HORIZ_ID: GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
  954.                        break;
  955.  
  956.         case LEFT_ID : GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
  957.                        step = max (HorizPot - WIDTH_STEP, 0);
  958. #ifndef LARGE
  959.                        SetGadAttrs (HorizGadget, FRA_win, NULL,
  960.                            PGA_Top,      step,
  961.                            PGA_Visible,  FRA_win->Width,
  962.                            PGA_Total,    Width,
  963.                            TAG_DONE);
  964. #else
  965.                        SetGadgetAttrs (HorizGadget, FRA_win, NULL,
  966.                            PGA_Top,      step,
  967.                            PGA_Visible,  FRA_win->Width,
  968.                            PGA_Total,    Width,
  969.                            TAG_DONE);
  970. #endif
  971.                        GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
  972.                        break;
  973.  
  974.         case RIGHT_ID: GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
  975.                        step = min (HorizPot + WIDTH_STEP, Width);
  976. #ifndef LARGE
  977.                        SetGadAttrs (HorizGadget, FRA_win, NULL,
  978.                            PGA_Top,      step,
  979.                            PGA_Visible,  FRA_win->Width,
  980.                            PGA_Total,    Width,
  981.                            TAG_DONE);
  982. #else
  983.                        SetGadgetAttrs (HorizGadget, FRA_win, NULL,
  984.                            PGA_Top,      step,
  985.                            PGA_Visible,  FRA_win->Width,
  986.                            PGA_Total,    Width,
  987.                            TAG_DONE);
  988. #endif
  989.                        GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
  990.                        break;
  991.  
  992.         case VERT_ID : GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
  993.                        break;
  994.  
  995.         case UP_ID   : GetAttr (PGA_Top, VertGadget,  (ULONG *)&VertPot);
  996.                        step = max (VertPot - HEIGHT_STEP, 0);
  997. #ifndef LARGE
  998.                        SetGadAttrs (VertGadget, FRA_win, NULL,
  999.                            PGA_Top,      step,
  1000.                            PGA_Visible,  FRA_win->Height,
  1001.                            PGA_Total,    Height,
  1002.                            TAG_DONE);
  1003. #else
  1004.                        SetGadgetAttrs (VertGadget, FRA_win, NULL,
  1005.                            PGA_Top,      step,
  1006.                            PGA_Visible,  FRA_win->Height,
  1007.                            PGA_Total,    Height,
  1008.                            TAG_DONE);
  1009. #endif
  1010.                        GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
  1011.                        break;
  1012.  
  1013.         case DOWN_ID : GetAttr (PGA_Top, VertGadget,  (ULONG *)&VertPot);
  1014.                        step = min (VertPot + HEIGHT_STEP, Height);
  1015. #ifndef LARGE
  1016.                        SetGadAttrs (VertGadget, FRA_win, NULL,
  1017.                            PGA_Top,      step,
  1018.                            PGA_Visible,  FRA_win->Height,
  1019.                            PGA_Total,    Height,
  1020.                            TAG_DONE);
  1021. #else
  1022.                        SetGadgetAttrs (VertGadget, FRA_win, NULL,
  1023.                            PGA_Top,      step,
  1024.                            PGA_Visible,  FRA_win->Height,
  1025.                            PGA_Total,    Height,
  1026.                            TAG_DONE);
  1027. #endif
  1028.                        GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
  1029.                        break;
  1030.     }
  1031.     if ((dX != ScrollX) || (dY != ScrollY)) {
  1032.       hrScrollSecondView (hrh, dX, dY);
  1033.       ScrollX = dX; ScrollY = dY;
  1034.     }
  1035. }
  1036.  
  1037. /*============================================================================*
  1038.  *  Auf Tastendruck reagieren.                                                *
  1039.  *============================================================================*/
  1040.  
  1041. static void
  1042. CheckKey (UWORD KeyID, ULONG Qualifier)
  1043. {
  1044.     int step, HorizPot, VertPot;
  1045.  
  1046.     ULONG dX = ScrollX, dY = ScrollY;
  1047.  
  1048.     switch (KeyID) {
  1049.         case KEY_LEFT:  GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
  1050.                         if (SHIFT_KEY(Qualifier)) {
  1051.                             step = max (HorizPot - FRA_win->Width, 0);
  1052.                         } else {
  1053.                             step = max (HorizPot - WIDTH_STEP, 0);
  1054.                         }
  1055. #ifndef LARGE
  1056.                         SetGadAttrs (HorizGadget, FRA_win, NULL,
  1057.                             PGA_Top,      step,
  1058.                             PGA_Visible,  FRA_win->Width,
  1059.                             PGA_Total,    Width,
  1060.                             TAG_DONE);
  1061. #else
  1062.                         SetGadgetAttrs (HorizGadget, FRA_win, NULL,
  1063.                             PGA_Top,      step,
  1064.                             PGA_Visible,  FRA_win->Width,
  1065.                             PGA_Total,    Width,
  1066.                             TAG_DONE);
  1067. #endif
  1068.                         GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
  1069.                         break;
  1070.  
  1071.         case KEY_RIGHT: GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
  1072.                         if (SHIFT_KEY(Qualifier)) {
  1073.                             step = min (HorizPot + FRA_win->Width, Width);
  1074.                         } else {
  1075.                             step = min (HorizPot + WIDTH_STEP, Width);
  1076.                         }
  1077. #ifndef LARGE
  1078.                         SetGadAttrs (HorizGadget, FRA_win, NULL,
  1079.                             PGA_Top,      step,
  1080.                             PGA_Visible,  FRA_win->Width,
  1081.                             PGA_Total,    Width,
  1082.                             TAG_DONE);
  1083. #else
  1084.                         SetGadgetAttrs (HorizGadget, FRA_win, NULL,
  1085.                             PGA_Top,      step,
  1086.                             PGA_Visible,  FRA_win->Width,
  1087.                             PGA_Total,    Width,
  1088.                             TAG_DONE);
  1089. #endif
  1090.                         GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
  1091.                         break;
  1092.  
  1093.         case KEY_UP:    GetAttr (PGA_Top, VertGadget,  (ULONG *)&VertPot);
  1094.                         if (SHIFT_KEY(Qualifier)) {
  1095.                             step = max (VertPot - FRA_win->Height, 0);
  1096.                         } else {
  1097.                             step = max (VertPot - HEIGHT_STEP, 0);
  1098.                         }
  1099. #ifndef LARGE
  1100.                         SetGadAttrs (VertGadget, FRA_win, NULL,
  1101.                             PGA_Top,      step,
  1102.                             PGA_Visible,  FRA_win->Height,
  1103.                             PGA_Total,    Height,
  1104.                             TAG_DONE);
  1105. #else
  1106.                         SetGadgetAttrs (VertGadget, FRA_win, NULL,
  1107.                             PGA_Top,      step,
  1108.                             PGA_Visible,  FRA_win->Height,
  1109.                             PGA_Total,    Height,
  1110.                             TAG_DONE);
  1111. #endif
  1112.                         GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
  1113.                         break;
  1114.  
  1115.         case KEY_DOWN:  GetAttr (PGA_Top, VertGadget, (ULONG *)&VertPot);
  1116.                         if (SHIFT_KEY(Qualifier)) {
  1117.                             step = min (VertPot + FRA_win->Height, Height);
  1118.                         } else {
  1119.                             step = min (VertPot + HEIGHT_STEP, Height);
  1120.                         }
  1121. #ifndef LARGE
  1122.                         SetGadAttrs (VertGadget, FRA_win, NULL,
  1123.                             PGA_Top,      step,
  1124.                             PGA_Visible,  FRA_win->Height,
  1125.                             PGA_Total,    Height,
  1126.                             TAG_DONE);
  1127. #else
  1128.                         SetGadgetAttrs (VertGadget, FRA_win, NULL,
  1129.                             PGA_Top,      step,
  1130.                             PGA_Visible,  FRA_win->Height,
  1131.                             PGA_Total,    Height,
  1132.                             TAG_DONE);
  1133. #endif
  1134.                         GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
  1135.                         break;
  1136.  
  1137.     /*    case KEY_MINUS:    fdelay++;
  1138.                         break;*/
  1139.     }
  1140.  
  1141.     if ((dX != ScrollX) || (dY != ScrollY)) {
  1142.       hrScrollSecondView (hrh, dX, dY);
  1143.       ScrollX = dX; ScrollY = dY;
  1144.     }
  1145. }
  1146.  
  1147. /*============================================================================*
  1148.  *  Auf Menuewahl reagieren.                                                  *
  1149.  *============================================================================*/
  1150.  
  1151. static void
  1152. ChangeWindow (int x, int y, int w, int h)
  1153. {
  1154.     int dx, dy;
  1155.  
  1156.     dx = x - FRA_win->LeftEdge;
  1157.     dy = y - FRA_win->TopEdge;
  1158.  
  1159.     if (dx || dy ) {
  1160.       MoveWindow (FRA_win, dx, dy);
  1161.       hrMoveSecondView (hrh, FRA_win->LeftEdge + left, FRA_win->TopEdge + top);
  1162.     }
  1163.     dx = w - FRA_win->Width;
  1164.     dy = h - FRA_win->Height;
  1165.  
  1166.     if (dx || dy ) {
  1167.       SizeWindow (FRA_win, dx, dy);
  1168.       Resize ();
  1169.     }
  1170. }
  1171.  
  1172. static void
  1173. ResetWindow (void)
  1174. {
  1175.     int ox, oy;
  1176.  
  1177.     ox = (hrh->ModeInfo->ResWidth  - InnerWidth) / 2;
  1178.     oy = (hrh->ModeInfo->ResHeight - InnerHeight) / 2;
  1179.  
  1180.     ChangeWindow (ox, oy, FRA_win->MaxWidth, FRA_win->MaxHeight);
  1181.     SetVar (ENVNAME, NULL, -1, GVF_GLOBAL_ONLY);
  1182. }
  1183.  
  1184. static void
  1185. CheckMenu (UWORD MenuNumber)
  1186. {
  1187.  UWORD ItemNum;
  1188.  struct MenuItem *Item;
  1189.  char envbuf[ENVSIZE];
  1190.  int winx, winy,
  1191.      winw, winh;
  1192.  
  1193.  while (MenuNumber != MENUNULL) {
  1194.       Item = (struct MenuItem *) ItemAddress (Menus, MenuNumber);
  1195.       ItemNum = ITEMNUM (MenuNumber);
  1196.  
  1197.       switch (MENUNUM (MenuNumber)) {
  1198.        case 0: switch (ItemNum) {
  1199.          case 0:
  1200. #ifndef LARGE
  1201.                 EasyReqArgs (FRA_win, &AboutRequest, NULL, (LONG *) NULL);
  1202. #else
  1203.                 EasyRequestArgs (FRA_win, &AboutRequest, NULL, (LONG *) NULL);
  1204. #endif
  1205.                 break;
  1206.  
  1207.          case 2:
  1208.          case 3: IEEEflag = !IEEEflag;
  1209.                  ZoomFlag = TRUE;
  1210.                  break;
  1211.  
  1212.          case 4: ResetMand();
  1213.                  break;
  1214.  
  1215.          case 6: Quit (NO_ERR);
  1216.        }
  1217.        break;
  1218.  
  1219.        case 1: switch (ItemNum) {
  1220.  
  1221.          case 0: ResetWindow ();
  1222.                  break;
  1223.  
  1224.          case 1: sprintf (envbuf ,"%d %d %d %d %G %G %G %G",
  1225.                             FRA_win->LeftEdge, FRA_win->TopEdge,
  1226.                             FRA_win->Width, FRA_win->Height,
  1227.                             RealLow, RealHigh, ImagLow, ImagHigh);
  1228.                  SetVar (ENVNAME, envbuf, -1, GVF_GLOBAL_ONLY);
  1229.                  break;
  1230.  
  1231.          case 2: if ((GetVar (ENVNAME, envbuf, ENVSIZE, GVF_GLOBAL_ONLY)) > 0) {
  1232.  
  1233.                     sscanf (envbuf, "%d %d %d %d %G %G %G %G",
  1234.                             &winx, &winy, &winw, &winh,
  1235.                             &RealLow, &RealHigh, &ImagLow, &ImagHigh);
  1236.  
  1237.                     winw = min (max (winw, FRA_win->MinWidth),  FRA_win->MaxWidth);
  1238.                     winh = min (max (winh, FRA_win->MinHeight), FRA_win->MaxHeight);
  1239.                     winx = min (max (winx, 0), FRA_win->WScreen->Width  - winw);
  1240.                     winy = min (max (winy, 0), FRA_win->WScreen->Height - winh);
  1241.                     ChangeWindow (winx, winy, winw, winh);
  1242.                  } else {
  1243.                     ResetWindow ();
  1244.                  }
  1245.                  break;
  1246.  
  1247.          case 4: ChangeWindow (FRA_win->LeftEdge, FRA_win->TopEdge,
  1248.                                FRA_win->MinWidth, FRA_win->MinHeight);
  1249.                  break;
  1250.  
  1251.          case 5: ChangeWindow  (min (FRA_win->WScreen->Width  - FRA_win->MaxWidth,
  1252.                                 FRA_win->LeftEdge),
  1253.                                 min (FRA_win->WScreen->Height - FRA_win->MaxHeight,
  1254.                                 FRA_win->TopEdge),
  1255.                                 FRA_win->MaxWidth, FRA_win->MaxHeight);
  1256.                  break;
  1257.        }
  1258.        break;
  1259.       }
  1260.       MenuNumber = Item->NextSelect;
  1261.  }
  1262. }
  1263.  
  1264. /*============================================================================*
  1265.  *  Rollbalken und Pfeilknoepfe erzeugen.                                     *
  1266.  *============================================================================*/
  1267.  
  1268. static void
  1269. AddGadgets (void)
  1270. {
  1271.     static struct TagItem ArrowMappings[] = { GA_ID, GA_ID, TAG_END };
  1272.     struct DrawInfo *DrawInfo;
  1273.     BOOL Borderless = FALSE;
  1274.     int ImageSize;
  1275.     UWORD Border;
  1276.     ULONG Mode;
  1277.  
  1278.     Mode = GetVPModeID (&Screen->ViewPort);
  1279.  
  1280.     if (Mode == INVALID_ID) {
  1281.         Mode = HIRES_KEY;
  1282.     }
  1283.     if ((Mode & HIRES_KEY) || ((Mode & MONITOR_ID_MASK) == MERLIN_KEY)) {    /* get system images */
  1284.         ImageSize = SYSISIZE_MEDRES;
  1285.         Border = 4;
  1286.     } else {
  1287.         ImageSize = SYSISIZE_LOWRES;
  1288.         Border = 3;
  1289.     }
  1290.  
  1291.     if (!(DrawInfo = (struct DrawInfo *) GetScreenDrawInfo (Screen)))
  1292.         Quit (DRI_ERR);
  1293.  
  1294.     UpImage = (struct Image *) NewObject (NULL, "sysiclass",
  1295.         SYSIA_Size,     ImageSize,
  1296.         SYSIA_Which,    UPIMAGE,
  1297.         SYSIA_DrawInfo, DrawInfo,
  1298.         TAG_END);
  1299.     DownImage = (struct Image *) NewObject (NULL, "sysiclass",
  1300.         SYSIA_Size,     ImageSize,
  1301.         SYSIA_Which,    DOWNIMAGE,
  1302.         SYSIA_DrawInfo, DrawInfo,
  1303.         TAG_END);
  1304.     LeftImage = (struct Image *) NewObject (NULL, "sysiclass",
  1305.         SYSIA_Size,     ImageSize,
  1306.         SYSIA_Which,    LEFTIMAGE,
  1307.         SYSIA_DrawInfo, DrawInfo,
  1308.         TAG_END);
  1309.     RightImage = (struct Image *) NewObject (NULL, "sysiclass",
  1310.         SYSIA_Size,     ImageSize,
  1311.         SYSIA_Which,    RIGHTIMAGE,
  1312.         SYSIA_DrawInfo, DrawInfo,
  1313.         TAG_END);
  1314.  
  1315.     FreeScreenDrawInfo (Screen, DrawInfo);
  1316.  
  1317.     if (!UpImage || !DownImage || !LeftImage || !RightImage)
  1318.         Quit (MEM_ERR);
  1319.  
  1320.     if ((SysBase->LibNode.lib_Version >= 39) &&        /* OS2.0 und Mono Roll- */
  1321.         (Screen->RastPort.BitMap->Depth > 1)) {        /* balken verbessern */
  1322.         Borderless = TRUE;
  1323.     }
  1324.     VertGadget = NewObject (NULL,"propgclass",
  1325.         GA_ID,          VERT_ID,
  1326.         GA_RelHeight,   - (UpImage->Height + DownImage->Height + RightImage->Height + (Screen->Font->ta_YSize + Screen->WBorTop + 1)) - 2,
  1327.         GA_Width,       DownImage->Width - 2 * Border,
  1328.         GA_Top,         (Screen->Font->ta_YSize + Screen->WBorTop + 1) + 1,
  1329.         GA_RelRight,    - (DownImage->Width - 2 * Border) - Border + 1,
  1330.         GA_Immediate,   TRUE,
  1331.         GA_FollowMouse, TRUE,
  1332.         GA_RelVerify,   TRUE,
  1333.         GA_RightBorder, TRUE,
  1334.         PGA_Borderless, Borderless,
  1335.         PGA_Freedom,    FREEVERT,
  1336.         PGA_NewLook,    TRUE,
  1337.         PGA_Visible,    1,
  1338.         PGA_Total,      1,
  1339.         TAG_DONE);
  1340.  
  1341.     UpGadget = NewObject (NULL,"buttongclass",
  1342.         GA_ID,          UP_ID,
  1343.         GA_Image,       UpImage,
  1344.         GA_Width,       UpImage->Width,
  1345.         GA_Height,      UpImage->Height,
  1346.         GA_RelBottom,   1 - RightImage->Height - DownImage->Height - UpImage->Height,
  1347.         GA_RelRight,    1 - UpImage->Width,
  1348.         GA_Immediate,   TRUE,
  1349.         GA_RelVerify,   TRUE,
  1350.         GA_Previous,    VertGadget,
  1351.         GA_RightBorder, TRUE,
  1352.         ICA_TARGET,     ICTARGET_IDCMP,
  1353.         ICA_MAP,        ArrowMappings,
  1354.         TAG_DONE);
  1355.  
  1356.     DownGadget = NewObject (NULL,"buttongclass",
  1357.         GA_ID,          DOWN_ID,
  1358.         GA_Image,       DownImage,
  1359.         GA_Width,       DownImage->Width,
  1360.         GA_Height,      DownImage->Height,
  1361.         GA_RelBottom,   1 - RightImage->Height - DownImage->Height,
  1362.         GA_RelRight,    1 - DownImage->Width,
  1363.         GA_Immediate,   TRUE,
  1364.         GA_RelVerify,   TRUE,
  1365.         GA_Previous,    UpGadget,
  1366.         GA_RightBorder, TRUE,
  1367.         ICA_TARGET,     ICTARGET_IDCMP,
  1368.         ICA_MAP,        ArrowMappings,
  1369.         TAG_DONE);
  1370.  
  1371.     HorizGadget = NewObject (NULL,"propgclass",
  1372.         GA_ID,          HORIZ_ID,
  1373.         GA_RelWidth,    - (LeftImage->Width + RightImage->Width + DownImage->Width + Screen->WBorLeft) - 1,
  1374.         GA_Height,      RightImage->Height - 2 * 2,
  1375.         GA_RelBottom,   - (RightImage->Height - 2 * 2) - 1,
  1376.         GA_Left,        Screen->WBorLeft - 1,
  1377.         GA_Immediate,   TRUE,
  1378.         GA_FollowMouse, TRUE,
  1379.         GA_RelVerify,   TRUE,
  1380.         GA_Previous,    DownGadget,
  1381.         GA_BottomBorder,TRUE,
  1382.         PGA_Borderless, Borderless,
  1383.         PGA_Freedom,    FREEHORIZ,
  1384.         PGA_NewLook,    TRUE,
  1385.         PGA_Visible,    1,
  1386.         PGA_Total,      1,
  1387.         TAG_DONE);
  1388.  
  1389.     LeftGadget = NewObject (NULL,"buttongclass",
  1390.         GA_ID,          LEFT_ID,
  1391.         GA_Image,       LeftImage,
  1392.         GA_RelRight,    1 - DownImage->Width - RightImage->Width - LeftImage->Width,
  1393.         GA_RelBottom,   1 - LeftImage->Height,
  1394.         GA_Height,      LeftImage->Height,
  1395.         GA_Width,       LeftImage->Width,
  1396.         GA_Immediate,   TRUE,
  1397.         GA_RelVerify,   TRUE,
  1398.         GA_Previous,    HorizGadget,
  1399.         GA_BottomBorder,TRUE,
  1400.         ICA_TARGET,     ICTARGET_IDCMP,
  1401.         ICA_MAP,        ArrowMappings,
  1402.         TAG_DONE);
  1403.  
  1404.     RightGadget = NewObject (NULL,"buttongclass",
  1405.         GA_ID,          RIGHT_ID,
  1406.         GA_Image,       RightImage,
  1407.         GA_Width,       RightImage->Width,
  1408.         GA_Height,      RightImage->Height,
  1409.         GA_RelBottom,   1 - RightImage->Height,
  1410.         GA_RelRight,    1 - DownImage->Width - RightImage->Width,
  1411.         GA_Immediate,   TRUE,
  1412.         GA_RelVerify,   TRUE,
  1413.         GA_Previous,    LeftGadget,
  1414.         GA_BottomBorder,TRUE,
  1415.         ICA_TARGET,     ICTARGET_IDCMP,
  1416.         ICA_MAP,        ArrowMappings,
  1417.         TAG_DONE);
  1418.  
  1419.     if (!LeftGadget || !RightGadget || !HorizGadget ||
  1420.         !UpGadget   || !DownGadget  || !VertGadget)
  1421.             Quit (MEM_ERR);
  1422.  
  1423.     /* Windowgroesse (Brutto) */
  1424.  
  1425.     Width  = InnerWidth + Screen->WBorLeft + DownImage->Width;
  1426.     Height = InnerHeight + (Screen->Font->ta_YSize + Screen->WBorTop + 1) + RightImage->Height;
  1427. }
  1428.  
  1429. /*============================================================================*
  1430.  *  Oeffnen eines Windows mit einem SecondView PIP.                           *
  1431.  *============================================================================*/
  1432.  
  1433. static char *
  1434. GetBaseName (char *name)
  1435. {
  1436.     char *fname;
  1437.  
  1438.     if (name) {
  1439.         if (name[strlen(name)-1] == '/') {
  1440.             name[strlen(name)-1] = '\0';
  1441.         }
  1442.         if (fname = strrchr (name, '/')) {
  1443.             return fname+1;
  1444.         } else if (fname = strrchr (name, ':')) {
  1445.             return fname+1;
  1446.         }
  1447.         return name;
  1448.     }
  1449.     return version+6;
  1450. }
  1451.  
  1452. static char *
  1453. GetTitle (char *name)
  1454. {
  1455.     if (name) {
  1456.         if (ZoomNr == 0) {
  1457.           sprintf (name,"%s = Left: %G Right: %G dX: %G dY: %G",
  1458.                     "Basic Set", RealLow, RealHigh, RealHigh-RealLow, ImagHigh-ImagLow);
  1459.         } else {
  1460.           sprintf (name,"Zoom %d = Left: %G Right: %G dX: %G dY: %G",
  1461.                     ZoomNr, RealLow, RealHigh, RealHigh-RealLow, ImagHigh-ImagLow);
  1462.         }
  1463.     }
  1464.     return name;
  1465. }
  1466.  
  1467. static void
  1468. OpenMerlinPIP (int w, int h)
  1469. {
  1470.     struct TagItem tags[17];
  1471.     struct HRList *hrl;
  1472.     struct HRHandle *hrh2;
  1473.     char envbuf[ENVSIZE];
  1474.     LONG cnt;
  1475.     int winx, winy, winw, winh;
  1476.     int ox, oy;
  1477.  
  1478.     hrl = hrLockHRList();
  1479.     hrh2 = hrl->laston;
  1480.     hrUnlockHRList (hrl);
  1481.  
  1482.     if (!hrh2 || !(Screen = hrh2->IScr)) {    /* Richtigen IntuiScreen suchen */
  1483.       Quit (FND_ERR);
  1484.     }
  1485.     if (hrh2->SecondView != NULL) {            /* Nur ein PIP erlaubt */
  1486.       Quit (DBL_ERR);
  1487.     }
  1488.     if ((hrh2->ModeInfo->ResWidth < 640) || (hrh2->ModeInfo->ResHeight < 400)) {
  1489.       Quit (PIP_ERR);
  1490.     }
  1491.  
  1492.     AddGadgets();
  1493.  
  1494.     left = Screen->WBorLeft;
  1495.     top  = Screen->Font->ta_YSize + Screen->WBorTop + 1;
  1496.  
  1497.     ox = (hrh2->ModeInfo->ResWidth  - w) / 2;
  1498.     oy = (hrh2->ModeInfo->ResHeight - h) / 2;
  1499.  
  1500.     cnt = 0;
  1501.  
  1502.     if ((GetVar (ENVNAME, envbuf, ENVSIZE, GVF_GLOBAL_ONLY)) > 0) {
  1503.         sscanf (envbuf, "%d %d %d %d %G %G %G %G",
  1504.                 &winx, &winy, &winw, &winh,
  1505.                 &RealLow, &RealHigh, &ImagLow, &ImagHigh);
  1506.         winw = min (max (winw, MIN_WIDTH),  Width);
  1507.         winh = min (max (winh, MIN_HEIGHT), Height);
  1508.         winx = min (max (winx, 0), hrh2->ModeInfo->ResWidth  - winw);
  1509.         winy = min (max (winy, 0), hrh2->ModeInfo->ResHeight - winh);
  1510.  
  1511.         SETTAG (WA_Left,    winx);
  1512.         SETTAG (WA_Top,     winy);
  1513.         SETTAG (WA_Width,   winw);
  1514.         SETTAG (WA_Height,  winh);
  1515.     } else {
  1516.         ox = (hrh2->ModeInfo->ResWidth  - w) / 2;
  1517.         oy = (hrh2->ModeInfo->ResHeight - h) / 2;
  1518.  
  1519.         SETTAG (WA_Left,    ox - left);
  1520.         SETTAG (WA_Top,     oy - top);
  1521.         SETTAG (WA_Width,   Width);
  1522.         SETTAG (WA_Height,  Height);
  1523.     }
  1524.     SETTAG (WA_Title,       version+6);
  1525.     SETTAG (WA_PubScreen,   Screen);
  1526.     SETTAG (WA_MaxWidth,    Width);
  1527.     SETTAG (WA_MaxHeight,   Height);
  1528.     SETTAG (WA_MinWidth,    MIN_WIDTH);
  1529.     SETTAG (WA_MinHeight,   MIN_HEIGHT);
  1530.     SETTAG (WA_IDCMP,       IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_RAWKEY |
  1531.                             IDCMP_INTUITICKS | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK |
  1532.                             IDCMP_CHANGEWINDOW | IDCMP_MOUSEBUTTONS);
  1533.     SETTAG (WA_Flags,       WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM | WFLG_ACTIVATE |
  1534.                             WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET );
  1535.     SETTAG (WA_Gadgets,     VertGadget);
  1536.     SETTAG (WA_ScreenTitle, GetTitle(fileName));
  1537.     SETTAG (WA_NewLookMenus,TRUE);
  1538.     SETTAG (TAG_END,        0);
  1539.  
  1540.     if (!(FRA_win = OpenWindowTagList (NULL, tags))) {  /* Window oeffnen */
  1541.       Quit (WIN_ERR);
  1542.     }
  1543.     rp = FRA_win->RPort;
  1544.  
  1545.     if (!(coltab = (ULONG *) malloc (256 * sizeof(ULONG))))
  1546.       Quit (MEM_ERR);
  1547.  
  1548.     hrGetPaletteRGBA (hrh2, coltab, 0, 255);    /* Farbpalette retten */
  1549.  
  1550.     hrAllocSecondView (hrh2, w, h, 0);            /* PIP erzeugen */
  1551.  
  1552.     hrh = hrh2;
  1553.     hrbm = &hrh->SecondView->BitMap;
  1554.  
  1555.     hrClearToCol (hrbm, 1);
  1556.  
  1557.     hrMoveSecondView (hrh, FRA_win->LeftEdge + left,
  1558.                            FRA_win->TopEdge  + top);
  1559.     Resize ();
  1560.  
  1561.     if (!(Menus = (struct Menu *) CreateMenus (NewMenu, TAG_DONE)))
  1562.       Quit (MEN_ERR);
  1563.  
  1564.     if (!(VisualInfo = (APTR) GetVisualInfo (Screen, TAG_DONE)))
  1565.       Quit (VIS_ERR);
  1566.  
  1567.     LayoutMenus (Menus, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE);
  1568.     SetMenuStrip (FRA_win, Menus);
  1569.  
  1570.     hrSwitchSecondView (hrh, TRUE);
  1571. }
  1572.  
  1573. /*============================================================================*
  1574.  * Print a usage message and exit
  1575.  *============================================================================*/
  1576.  
  1577. /*============================================================================*
  1578.  * Main :)
  1579.  *============================================================================*/
  1580.  
  1581. static char template[] =
  1582.     "W=Width/K/N,H=Height/K/N,"
  1583.     "B=Box/K/N,D=Depth/K/N,Q=Quiet/S";
  1584.  
  1585. static char usage[] =
  1586.     " Width <n>  - Sets the width of the Merlin-PIP\n"
  1587.     " Height <n> - Sets the height of the Merlin-PIP\n"
  1588.     " Box <n>    - Sets the zoom box (indirectly, 1/nth of InnerWidth/Height)\n"
  1589.     " Depth <n>  - Sets the iteration depth\n"
  1590.     " Quiet      - Supresses printing of timing information, and most error\n"
  1591.     "              messages.\n";
  1592.  
  1593. struct {
  1594.     int  *width;
  1595.     int  *height;
  1596.     int  *box;
  1597.     int  *depth;
  1598.     LONG Quiet;
  1599. } cliarray = {
  1600.     NULL, NULL, NULL, NULL, 0
  1601. };
  1602.  
  1603. /*
  1604.  *--------------------------------------------------------------
  1605.  *
  1606.  * main --
  1607.  *
  1608.  *      Parses command line, starts decoding and displaying.
  1609.  *
  1610.  * Results:
  1611.  *      None.
  1612.  *
  1613.  * Side effects:
  1614.  *      None.
  1615.  *
  1616.  *--------------------------------------------------------------
  1617.  */
  1618.  
  1619. static void
  1620. ParseArgs (void)
  1621. {
  1622.     struct RDArgs *cliargs;
  1623.  
  1624.     wwidth  = 320;
  1625.     wheight = 256;
  1626.  
  1627.     if (!(cliargs = ReadArgs (template, (LONG *)&cliarray, NULL))) {
  1628.         SET_A_PEN(3); OUTPUT1 ("%s", &version[6]); SET_A_PEN(1);
  1629.         OUTPUT1 ("\n%s\n", template);
  1630.         OUTPUT1 ("\n%s\n", usage);
  1631.         exit (NO_ERR);
  1632.     }
  1633.     if (cliarray.Quiet)  quietFlag = TRUE;
  1634.     if (cliarray.width)  wwidth = *cliarray.width;
  1635.     if (cliarray.height) wheight = *cliarray.height;
  1636.     if (cliarray.depth)  MaxIteration = *cliarray.depth;
  1637.     if (cliarray.box)    ZoomBox = *cliarray.box;
  1638.  
  1639.     FreeArgs (cliargs);
  1640. }
  1641.  
  1642. static void
  1643. ParseToolTypes ()
  1644. {
  1645.     struct DiskObject *dobj;
  1646.     char **toolarray, *s, *Directory = NULL;
  1647.     struct WBArg *wbarg;
  1648.     SHORT i;
  1649.     char buffer[256];
  1650.  
  1651.     quietFlag = TRUE;
  1652.  
  1653.     if (!(IconBase = OpenLibrary ("icon.library", 33))) {
  1654.         return;
  1655.     }
  1656.     for (i=0, wbarg=_WBenchMsg->sm_ArgList; i < _WBenchMsg->sm_NumArgs; i++, wbarg++) {
  1657.  
  1658.         if (!i) {
  1659.             wbarg->wa_Lock = GetProgramDir ();
  1660.             NameFromLock (wbarg->wa_Lock, buffer, 255);
  1661.             AddPart (buffer, wbarg->wa_Name, 255);
  1662.  
  1663.             if (*buffer && (dobj = GetDiskObject (buffer))) {
  1664.                 toolarray = (char **)dobj->do_ToolTypes;
  1665.  
  1666.                 if (s = (char *) FindToolType (toolarray, "WIDTH")) {
  1667.                   wwidth = atoi (s);
  1668.                 }
  1669.                 if (s = (char *) FindToolType (toolarray, "HEIGHT")) {
  1670.                   wheight = atoi (s);
  1671.                 }
  1672.                 if (s = (char *) FindToolType (toolarray, "DEPTH")) {
  1673.                   MaxIteration = atoi (s);
  1674.                 }
  1675.                 if (s = (char *) FindToolType (toolarray, "BOX")) {
  1676.                   ZoomBox = atoi (s);
  1677.                 }
  1678.                 FreeDiskObject (dobj);
  1679.             }
  1680.         } else if (!fileName) {
  1681.             NameFromLock (wbarg->wa_Lock, buffer, 255);
  1682.             AddPart (buffer, wbarg->wa_Name, 255);
  1683.           /*  fileName = strdup (buffer); */
  1684.         }
  1685.     }
  1686.     CloseLibrary (IconBase);
  1687.  
  1688. /*    if (!fileName) {
  1689.         if (!(ASLRequestFile (Directory))) {
  1690.             exit (NO_ERR);
  1691.         }
  1692.     }
  1693.     if (Directory) free (Directory);
  1694. */
  1695. }
  1696.  
  1697. /*============================================================================*/
  1698.  
  1699. void
  1700. main ()
  1701. {
  1702.     MYTIMEVAL tv;
  1703.  
  1704.     if (_WBenchMsg == NULL)
  1705.       ParseArgs ();
  1706.     else
  1707.       ParseToolTypes ();
  1708.  
  1709.     if (!quietFlag) {
  1710.       SET_A_PEN(3); OUTPUT1 ("%s", &version[6]); SET_A_PEN(1);
  1711.     }
  1712. /*
  1713.     if (!verbose)
  1714.         quietFlag = TRUE;
  1715.  
  1716.     if (argc != 1) {
  1717.       if (!ASLRequestFile (NULL))
  1718.         usage();
  1719.     }
  1720.     else {
  1721.         strcpy (fileName, argv[1]);
  1722.     }  
  1723.  
  1724.     if (argc == 1 && argv[1][0] == '?')
  1725.         usage();
  1726. */
  1727.     stdout = Output();
  1728.  
  1729. /*============================================================================*
  1730.  *  Initialisieren und Oeffnen des Displays.
  1731.  *============================================================================*/
  1732.  
  1733.     InitLibraries();
  1734.  
  1735.     /* Create a wwidth x wheight window to show the fract */
  1736.  
  1737.     InnerWidth  = wwidth;    /* Animationsgroesse (netto) merken */
  1738.     InnerHeight = wheight;
  1739.  
  1740.     FrameSize = wwidth * wheight;
  1741.  
  1742.     ResetMand();
  1743.  
  1744.     OpenMerlinPIP (wwidth, wheight);
  1745.  
  1746.     tv.LeftSeconds = 0;        /* initial values for testing double-click */
  1747.     tv.LeftMicros  = 0;
  1748.     tv.RightSeconds = 0;
  1749.     tv.RightMicros  = 0;
  1750.  
  1751. /*============================================================================*/
  1752.  
  1753.     if (!IEEEflag)
  1754.       MandelbrotInt32II();
  1755.     else
  1756.       Mandelbrot881();
  1757.  
  1758. /*============================================================================*
  1759.  * IDCMP-Messages am Window-UserPort abfragen und entsprechende Maßnahmen     *
  1760.  * ergreifen.                                                                 *
  1761.  *============================================================================*/
  1762.  
  1763.     while (TRUE) {
  1764.       ZoomFlag = FALSE;
  1765.       while (imsg = (struct IntuiMessage *) GetMsg (FRA_win->UserPort)) {
  1766.         msg = *imsg;
  1767.         ReplyMsg ((struct Message *) imsg);
  1768.         switch (msg.Class) {
  1769.           case IDCMP_CLOSEWINDOW : Quit (NO_ERR);
  1770.           case IDCMP_CHANGEWINDOW: hrMoveSecondView (hrh, FRA_win->LeftEdge + left,
  1771.                                                           FRA_win->TopEdge  + top);
  1772.                                    Resize ();
  1773.                                    break;
  1774.           case IDCMP_GADGETDOWN  : CurrentGadget = GADGETID(msg);
  1775.                                    break;
  1776.           case IDCMP_GADGETUP    : CheckGadget (CurrentGadget);
  1777.                                    CurrentGadget = NO_GADGET;
  1778.                                    break;
  1779.           case IDCMP_INTUITICKS  : CheckGadget (CurrentGadget);
  1780.                                    break;
  1781.           case IDCMP_RAWKEY      : CheckKey (msg.Code, msg.Qualifier);
  1782.                                    break;
  1783.           case IDCMP_MENUPICK    : CheckMenu (msg.Code);
  1784.                                    break;
  1785.           case IDCMP_MOUSEBUTTONS:
  1786.             switch (msg.Code) {
  1787.  
  1788.               case SELECTDOWN:
  1789.                 if (DoubleClick (tv.LeftSeconds, tv.LeftMicros, msg.Seconds, msg.Micros))
  1790.                     DoZoom (&msg);
  1791.                 else {
  1792.                     tv.LeftSeconds = msg.Seconds;
  1793.                     tv.LeftMicros  = msg.Micros;
  1794.                     tv.RightSeconds = 0;
  1795.                     tv.RightMicros  = 0;
  1796.                 }
  1797.                 break;
  1798.  
  1799.               case MENUDOWN:    /* not reached, but looks nice :) */
  1800.                 if (DoubleClick(tv.RightSeconds, tv.RightMicros, msg.Seconds, msg.Micros))
  1801.                     DoZoom (&msg);
  1802.                 else {
  1803.                     tv.LeftSeconds = 0;
  1804.                     tv.LeftMicros  = 0;
  1805.                     tv.RightSeconds = msg.Seconds;
  1806.                     tv.RightMicros  = msg.Micros;
  1807.                 }
  1808.                 break;
  1809.             }
  1810.             break;
  1811.         }
  1812.       }
  1813.       if (ZoomFlag){
  1814.         if (!IEEEflag)
  1815.           MandelbrotInt32II();
  1816.         else
  1817.           Mandelbrot881();
  1818.       }
  1819.     }
  1820. }
  1821.  
  1822.